/*
 * RouteWidget.cpp
 *
 *  Created on: Jan 13, 2011
 *      Author: kmueller
 */

#include "RouteWidget.h"

#include "SearchWidget.h"
#include "SettingsWidget.h"

#include "../logic/Main.h"
#include "../logic/Exceptions.h"
#include "../logic/Helpers.h"
#include "../logic/PositioningSystem.h"
#include "../logic/RoutingService.h"

#include "../core/MapReader.h"
#include "../core/MapRouter.h"
#include "../core/Road.h"
#include "../core/Route.h"

#include <QtGui>

using namespace opennav;

RouteComboBox::RouteComboBox(SearchWidget::Type t, int index,
		RouteWidget* parent) :
	QComboBox(parent) {
	type = t;
	addItem("");
	addItem(tr("Current GPS location"));
	addItem(tr("look for position..."));
	setCurrentIndex(index);

connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(indexChanged(int)));
}

void RouteComboBox::indexChanged(int index) {
	if ((index == 0 && itemText(0) == "") || index == 2) {
		hidePopup();
		SearchWidget search(type, static_cast<RouteWidget*> (parent()));
		search.exec();
	}
}

void RouteComboBox::setEntry(const LabeledCoordinate& coord) {
	setItemText(0, coord.getLabel());
	setCurrentIndex(0);
	coordinate = coord;
}

/*
 LabeledCoordinate RouteComboBox::value() const {
 switch (currentIndex()) {
 case 0: {
 if (coordinate.isValid()) {
 return coordinate;
 }
 throw InvalidSelectionException();
 }
 case 1: {
 QtMobility::QGeoCoordinate
 geo =
 Main::getInstance().getPositioningSystem().getLastPosition().coordinate();

 return LabeledCoordinate("Current GPS location", geo);
 }
 default:
 throw InvalidSelectionException();
 }
 }

 bool RouteComboBox::validSelection() const {
 return currentIndex() == 0 && coordinate.isValid() || currentIndex() == 1;
 }
 */

RouteWidget::RouteWidget(QWidget *parent) :
	QDialog(parent) {

	setWindowTitle(tr("Route calculation"));

	const Main& main = Main::getInstance();
	model = main.getRouteSettings();

	createComponents();
	createLayout();

	connect(&main.getRoutingService(), SIGNAL(startNavigation()), this, SLOT(
			close()));
	connect(&main.getRoutingService(), SIGNAL(noRoute()), this, SLOT(noRoute()));

	update();
}

void RouteWidget::setModel(RouteSettings* m) {
	model = m;
	update();
}

void RouteWidget::createComponents() {
	origin = new RouteComboBox(SearchWidget::ORIGIN, 1);

	destination = new RouteComboBox(SearchWidget::DESTINATION, 0);

	Settings& s = Main::getInstance().getSettings();
	routecalc = new SettingsComboBox(s.getRouteCalculation());
	connect(routecalc, SIGNAL(currentIndexChanged(int)), model, SLOT(setPreferredRoute(int)));

	avoidHighways = new QCheckBox(tr("Avoid highways"));
	connect(avoidHighways, SIGNAL(stateChanged(int)), model, SLOT(avoidHighways(int)));

	avoidTollroads = new QCheckBox(tr("Avoid tollroads"));
connect(avoidTollroads, SIGNAL(stateChanged(int)), model, SLOT(avoidTollroads(int)));
}

void RouteWidget::update() {
	origin->setEntry(model->getOrigin());
	destination->setEntry(model->getDestination());

	routecalc->setCurrentIndex(model->getPreferredRoute());
	avoidHighways->setCheckState(model->isAvoidHighways() ? Qt::Checked
			: Qt::Unchecked);
	avoidTollroads->setCheckState(model->isAvoidTollroads() ? Qt::Checked
			: Qt::Unchecked);
}

void RouteWidget::createLayout() {
	QFormLayout *leftLayout = new QFormLayout();

	leftLayout->addRow(tr("Origin: "), origin);
	leftLayout->addRow(tr("Destination: "), destination);
	leftLayout->addRow(tr("Preferred route: "), routecalc);
	leftLayout->addWidget(avoidHighways);
	leftLayout->addWidget(avoidTollroads);

	QPushButton *bCalc = new QPushButton(tr("Calculate"));
	connect(bCalc, SIGNAL(clicked()), this, SLOT(calculate()));
	QPushButton *bClose = new QPushButton(tr("Close"));
	connect(bClose, SIGNAL(clicked()), this, SLOT(close()));

	QBoxLayout *buttons = new QVBoxLayout();
	buttons->addStretch();
	buttons->addWidget(bCalc);
	buttons->addWidget(bClose);

	QBoxLayout* mainLayout = new QHBoxLayout();
	mainLayout->addLayout(leftLayout, 8);
	mainLayout->addLayout(buttons, 1);

	this->setLayout(mainLayout);
}

void RouteWidget::calculate() {
	RoutingService& route = Main::getInstance().getRoutingService();
	route.setSettings(model);
	if (!route.calculate()) {
		QMessageBox::warning(
				this,
				tr("Route calculation in progress"),
				tr("Route calculation is currently in progress. Please be patient."));
	}
}

void RouteWidget::noRoute() {
	QMessageBox::warning(this, tr("No route found"), tr(
			"Couldn't find route. Please change calculation parameters."));
}

void RouteWidget::setOrigin(const LabeledCoordinate& coord) {
	model->setOrigin(coord);
	update();
}

void RouteWidget::setDestination(const LabeledCoordinate& coord) {
	model->setDestination(coord);
	update();
}
